package com.zenchn.service.impl;


import com.zenchn.dao.TSysAuthorityMapper;
import com.zenchn.dynamic.TSysAuthorityDynamicMapper;
import com.zenchn.entity.MenuVO;
import com.zenchn.enums.AuthTypeEnum;
import com.zenchn.enums.DictTypeEnum;
import com.zenchn.generic.GenericDao;
import com.zenchn.generic.GenericServiceImpl;
import com.zenchn.model.TSysAuthority;
import com.zenchn.model.TSysAuthorityExample;
import com.zenchn.model.TSysDict;
import com.zenchn.model.TSysOauthClient;
import com.zenchn.entity.TSysAuthorityVO;
import com.zenchn.service.AuthorityService;
import com.zenchn.service.DictService;
import com.zenchn.service.OauthClientService;
import org.springframework.beans.BeanUtils;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import static org.mybatis.dynamic.sql.SqlBuilder.*;
import static com.zenchn.dynamic.TSysAuthorityDynamicSqlSupport.*;

/**
 * 权限Service实现类
 *
 * @author dingxinfa
 * @date 2020-04-16
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class AuthorityServiceImpl extends GenericServiceImpl<TSysAuthority, String, TSysAuthorityExample> implements AuthorityService {

    @Resource
    private TSysAuthorityMapper authorityMapper;

	@Resource
	private TSysAuthorityDynamicMapper authorityDynamicMapper;

	@Resource
	private OauthClientService oauthClientService;

	@Resource
	private DictService dictService;

	@Override
	public GenericDao<TSysAuthority, String, TSysAuthorityExample> getDao() {
		return authorityMapper;
	}


	@Override
	public List<TSysAuthorityVO> selectCascadeAuthList() {
		List<TSysOauthClient> oauthClientList=oauthClientService.selectByExample(null);
		List<TSysDict>  authTypeList=dictService.selectByDictTypeId(DictTypeEnum.AUTH_TYPE_GROUP.getId());


		TSysAuthorityExample example=new TSysAuthorityExample();

   		example.createCriteria().andAuthLevelEqualTo(1);
   		example.setOrderByClause("sorts asc");
   		
   		return subsetAuthList(oauthClientList,authTypeList,authorityMapper.selectByExample(example));
	}

	private List<TSysAuthorityVO> subsetAuthList(List<TSysOauthClient> oauthClientList, List<TSysDict>  authTypeList, List<TSysAuthority> authList){
		List<TSysAuthorityVO>  authorityVOList=new ArrayList<>();
		for(TSysAuthority auth:authList){
			TSysAuthorityVO  authVO=new TSysAuthorityVO();
			BeanUtils.copyProperties(auth,authVO);
			for (TSysOauthClient oauthClient:oauthClientList){
				if (authVO.getOauthClientId().equals(oauthClient.getClientId())){
					authVO.setOauthClientName(oauthClient.getClientName());
				}
			}

			for (TSysDict authType:authTypeList) {
				if (authType.getDictId().equals(authVO.getAuthTypeId())) {
					authVO.setAuthTypeName(authType.getDictName());
				}
			}


			TSysAuthorityExample example=new TSysAuthorityExample();
			example.createCriteria().andParentIdEqualTo(auth.getAuthId());
			example.setOrderByClause("sorts asc");
			long count=authorityMapper.countByExample(example);
			if(count>0){
				authVO.setChildren(subsetAuthList(oauthClientList,authTypeList,authorityMapper.selectByExample(example)));
			}

			authorityVOList.add(authVO);
		}
		return authorityVOList;
	}
	
	@Override
	public String findFullCascadeParentName(String authId) {
		
		List<TSysAuthority> auths=fullCascadeAuth(new LinkedList<TSysAuthority>(),authId);
		StringBuilder sb=new StringBuilder();
		for(TSysAuthority auth:auths){
			if(sb.length()>0){
				sb.append(" >> ");
			}
			sb.append(auth.getAuthName());
		}
		return sb.toString();
	}
	
	@Override
	public List<TSysAuthority> findFullCascade(String authId) {
		return fullCascadeAuth(new LinkedList<TSysAuthority>(),authId);
	}



	private List<TSysAuthority> fullCascadeAuth(LinkedList<TSysAuthority> auths, String authId) {
		TSysAuthority auth=authorityMapper.selectByPrimaryKey(authId);
		auths.add(0, auth);
		if(null!= auth.getParentId()&& !"".equals(auth.getParentId().trim())){
			fullCascadeAuth(auths,auth.getParentId());
		}
		return auths;
	}



	@Override
	public List<MenuVO> getMenuList(String oauthClientId, List<String> authIdList) {

		List<String> authTypeIdList=new ArrayList<>(Arrays.asList(AuthTypeEnum.CATALOG.getId(), AuthTypeEnum.MENU.getId()));

		TSysAuthorityExample example=new TSysAuthorityExample();
		TSysAuthorityExample.Criteria criteria=example.createCriteria();
		criteria.andAuthLevelEqualTo(1);
		criteria.andAuthIdIn(authIdList);
		criteria.andAuthTypeIdIn(authTypeIdList);
		criteria.andOauthClientIdEqualTo(oauthClientId);
		example.setOrderByClause("sorts asc");

		return childrenMenuList(oauthClientId,authIdList,authTypeIdList,authorityMapper.selectByExample(example));
	}


	private List<MenuVO>  childrenMenuList(String oauthClientId, List<String> authIdList, List<String> authTypeIdList, List<TSysAuthority> authList) {
		List<MenuVO> menuVOList = new ArrayList<>();
		for (TSysAuthority auth : authList) {
			MenuVO menuVO = new MenuVO();
			menuVO.setId(auth.getAuthId());
			menuVO.setLevel(auth.getAuthLevel());
			menuVO.setName(auth.getAuthName());
			menuVO.setIcon(auth.getIconStyle());
			menuVO.setUrl(auth.getUrl());
			menuVO.setTarget(auth.getTarget());

			TSysAuthorityExample example = new TSysAuthorityExample();
			TSysAuthorityExample.Criteria criteria = example.createCriteria();
			criteria.andParentIdEqualTo(auth.getAuthId());
			criteria.andAuthIdIn(authIdList);
			criteria.andAuthTypeIdIn(authTypeIdList);
			criteria.andOauthClientIdEqualTo(oauthClientId);
			example.setOrderByClause("sorts asc");
			long count = authorityMapper.countByExample(example);
			if (count > 0) {
				menuVO.setChildren(childrenMenuList(oauthClientId, authIdList, authTypeIdList, authorityMapper.selectByExample(example)));
			}
			menuVOList.add(menuVO);
		}
		return menuVOList;
	}


	@Override
	public Boolean verifyAuthSign(String authId, String authSign) {
		TSysAuthorityExample example = new TSysAuthorityExample();
		TSysAuthorityExample.Criteria criteria = example.createCriteria();

		criteria.andAuthSignEqualTo(authSign);
		if (null != authId && !"".equals(authId.trim())) {
			criteria.andAuthIdNotEqualTo(authId.trim());
		}

		if (authorityMapper.countByExample(example) > 0) {
			return false;
		}
		return true;
	}

}
